package com.danawa.watcher.util;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.io.IOException;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.annotations.XYTextAnnotation;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.DateTickUnit;
import org.jfree.chart.axis.DateTickUnitType;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.axis.TickUnit;
import org.jfree.chart.axis.TickUnits;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYStepRenderer;
import org.jfree.data.time.Day;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.TextAnchor;

import com.danawa.watcherApi.database.domain.PriceHistory;

public class JChartUtil {
	
	public static  void displayChart(String title,List<PriceHistory> data, HttpServletResponse response) throws IOException {
    	createChart(title,700 , 400 ,data, response);
    }
	
	public static  void displayChart(String title, int width, int height, List<PriceHistory> data, HttpServletResponse response) throws IOException {
    	createChart(title,width , height ,data, response);
    }
	
	/**
     * Displays a sample chart in its own frame.
     * @throws IOException 
     */
    private static void createChart(String title,  int width, int height, List<PriceHistory> dataList, HttpServletResponse response) throws IOException {

            final XYDataset data = createStepXYDataset(dataList);
            
            final JFreeChart chart = ChartFactory.createXYStepChart(
                title,	//차트 타이틀
                "Date", //가로 타이틀
                "Price",	// 세로 타이틀
                data,	//뿌려줄 데이타 
                PlotOrientation.VERTICAL,	//그래프 기준값 VERTICAL 수직
                true,   // legend
                true,   // tooltips
                false   // urls
            );
            
            //서브 타이틀 
            //TextTitle textTitleSub = new TextTitle(subTitle);
            //chart.addSubtitle(0, textTitleSub);
           
            //그래프 점석색
            chartPaint(chart);
            //그래프 폰트
            chartFont(chart);
            //차트 범위 설정
            chartAxis(chart, "");
            //그래프  가격 노출
            chartMoney(chart);
            
        	ServletOutputStream sos = response.getOutputStream();
            ChartUtilities.writeChartAsPNG(sos, chart, width, height);
    }
    
    /**
     * 차트 가격 노출
     * @param chart
     */
    public static void chartMoney(JFreeChart chart){
    	final XYPlot plot = chart.getXYPlot();
    	final XYDataset data = chart.getXYPlot().getDataset();
    	NumberFormat nf = NumberFormat.getInstance();
    	
    	//최저가
    	double minMoney =  data.getYValue(1, data.getItemCount(1)-1);
    	XYTextAnnotation minText = new XYTextAnnotation(nf.format(minMoney),  data.getX(1, data.getItemCount(1)-1).doubleValue(), minMoney);
    	minText.setFont(new Font("Arial", Font.PLAIN, 12));
    	minText.setTextAnchor(TextAnchor.BOTTOM_RIGHT);
    	
    	//최고가
    	double maxMoney  = data.getYValue(2, data.getItemCount(2)-1);
    	XYTextAnnotation maxText = new XYTextAnnotation(nf.format(maxMoney),  data.getX(2, data.getItemCount(2)-1).doubleValue(), maxMoney);
    	maxText.setFont(new Font("Arial", Font.PLAIN, 12));
    	maxText.setTextAnchor(TextAnchor.TOP_RIGHT);
    	
    	if(minMoney != maxMoney){
    		plot.addAnnotation(minText);
        	plot.addAnnotation(maxText);
    	}
        
    	//second y축 현재가 노출방식 현재가
    	double nowMoney  = data.getYValue(0, data.getItemCount(0)-1);
        final NumberAxis axis2 = new NumberAxis("");
        TickUnits xtickUnits = new TickUnits(); 
        xtickUnits.add(new NumberTickUnit(nowMoney));
        int minRange =  (int) (minMoney - (minMoney * 0.01));
        int maxRange =  (int) (maxMoney + (maxMoney * 0.01));
        axis2.setRange(minRange, maxRange);
        axis2.setStandardTickUnits(xtickUnits);
        plot.setRangeAxis(1, axis2);
    }
    
    /**
     * 차트 범위 설정
     * @param chart
     */
    public static void chartAxis (JFreeChart chart, String gubun){
    	final XYPlot plot = chart.getXYPlot();
    	final XYDataset data = chart.getXYPlot().getDataset();
    	
    	if(gubun.equals("hour")){
    		plot.getDomainAxis().setAutoTickUnitSelection(false);
		}

    	//x축 날짜 범위
		TickUnits xtickUnits = new TickUnits(); 
		double startDay =  data.getXValue(0, 0);
		double endDay  =  data.getXValue(0, data.getItemCount(0)-1);
		int scopeDay = (int) ((endDay - startDay)/86400000) ;
		if(scopeDay > 1){
			scopeDay = (int) Math.ceil(scopeDay / (double)9);
		}
		TickUnit	xunit = new DateTickUnit(DateTickUnitType.DAY,scopeDay);
	
        //x축 날짜 탑입 (x축은  Domain)
        final DateAxis axis = (DateAxis) plot.getDomainAxis();
        xtickUnits.add(xunit); 
        axis.setStandardTickUnits(xtickUnits);
        axis.setDateFormatOverride(new SimpleDateFormat("yy/MM/dd"));
		
        //y축 숫자 탑입 (y축은  Range)
        final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
        int minMoney =  (int) (data.getYValue(1, 0) - (data.getYValue(1, 0) * 0.01));
        int maxMoney =  (int) (data.getYValue(2, 0) + (data.getYValue(2, 0) * 0.01));
        rangeAxis.setRange(minMoney, maxMoney);
    }
    /**
     * 그래프 폰트 설정
     * @param chart
     */
    public static void chartFont (JFreeChart chart){
    	Font labelFont = null;
    	 //제목 및 서브 제목 한글 처리 폰트
        labelFont = chart.getTitle().getFont();
        chart.getTitle().setFont(new Font("Malgun Gothic", labelFont.getStyle(), labelFont.getSize()));
        chart.getLegend().setItemFont(new Font("Malgun Gothic", Font.PLAIN, 12));
        
        final XYPlot plot = chart.getXYPlot();
        //가로축 제목
        labelFont = plot.getDomainAxis().getLabelFont();
        plot.getDomainAxis().setLabelFont(new Font("Malgun Gothic", labelFont.getStyle(), labelFont.getSize()));
        
        //가로축 값에 대한 레이블
        labelFont = plot.getDomainAxis().getTickLabelFont();
        plot.getDomainAxis().setTickLabelFont(new Font("Arial", labelFont.getStyle(), 12));
        
        //세로축 제목
        labelFont = plot.getRangeAxis().getLabelFont();
        plot.getRangeAxis().setLabelFont(new Font("Malgun Gothic", labelFont.getStyle(), labelFont.getSize()));
         
        //세로축 값에 대한 레이블
        labelFont = plot.getRangeAxis().getTickLabelFont();
        plot.getRangeAxis().setTickLabelFont(new Font("Arial", labelFont.getStyle(), labelFont.getSize()));
    }
    
    /**
     * 그래프 백그라운드 점석 색
     * @param chart
     */
    public static void chartPaint (JFreeChart chart){
    	//차트 전체 배경색 지정
        chart.setBackgroundPaint(Color.WHITE);
        //차트 라운드 지정여부
        chart.setBorderVisible(true);
        
        final XYPlot plot = chart.getXYPlot();
    	//차트 노데이타
    	plot.setNoDataMessage("No Data available (데이타가 없음)");
    	//그래프 배경섹
    	plot.setBackgroundPaint(Color.WHITE);
    	//백그라운드 가로 점선 색
    	plot.setDomainGridlinePaint(Color.lightGray);
    	//백그라운드 세로 점선 색
    	plot.setRangeGridlinePaint(Color.lightGray);
    	
    	//그래프 차트 선 투께 및 모양
        final  XYStepRenderer renderer = (XYStepRenderer) plot.getRenderer();
        renderer.setSeriesPaint(0, new Color(9, 152, 38));
        renderer.setSeriesPaint(1, new Color(236, 78, 21));
        renderer.setSeriesPaint(2, new Color(230, 41, 41));
        renderer.setSeriesStroke(0, new BasicStroke(2) );
        renderer.setSeriesStroke(1, new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, new float[] {10.0f}, 0.0f) );
        renderer.setSeriesStroke(2, new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, new float[] {10.0f}, 0.0f) );
        
        //x축 설명 라인 노출 여부
        renderer.setSeriesLinesVisible(0, true);
        plot.setRenderer(renderer);
    }
    
    /**
     *  그래프 가격 데이타
     * @param data
     * @return
     */
    public static XYDataset createStepXYDataset(List<PriceHistory> data) {

    	final TimeSeriesCollection dataset = new TimeSeriesCollection();
    	
        List<Integer> sort = new ArrayList<Integer>();
        
        if(data.size() > 0){
        	final TimeSeries s1 = new TimeSeries  ("가격");
        	for(PriceHistory prod : data){
        		s1.addOrUpdate(new Day(prod.getInputDateTime()) , prod.getPrice());
        		sort.add(prod.getPrice());
        	}
        	int minPrice = Collections.min(sort);
        	int maxPrice = Collections.max(sort);
        	
        	final TimeSeries s2 = new TimeSeries  ("최저가");
        	final TimeSeries s3 = new TimeSeries  ("최고가");
        	
        	for(PriceHistory prod : data){
        		s2.addOrUpdate(new Day(prod.getInputDateTime())  , minPrice);
        		s3.addOrUpdate(new Day(prod.getInputDateTime())  , maxPrice);
	       	}
        	
        	if(s1.getItemCount() == 1){
    			long yesterDay = data.get(0).getInputDateTime().getTime() - 86400000;
    			s1.addOrUpdate(new Day(new Date(yesterDay)) , data.get(0).getPrice());
    			s2.addOrUpdate(new Day(new Date(yesterDay))  , minPrice);
        		s3.addOrUpdate(new Day(new Date(yesterDay))  , maxPrice);
    		}
        	
        	dataset.addSeries(s1);
            dataset.addSeries(s2);
            dataset.addSeries(s3);
        }

        return dataset;
    }
}
